﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Vim25Api;

namespace VmwareSeacher
{
    //日志级别
    public enum log_level
    {
        LOG_DEBUG,
        LOG_INFO,
        LOG_WARNING,
        LOG_ERROR,
    };
    

    public partial class VmSearcher : Form 
    {
        Config config;
        string VMWARE_SEARCHER_CONFIG_FILE = Application.StartupPath + "\\" + "vmwaresearcher.ini";
        private int curpos = 0;
        private int connections_num = 0;    //已经连接的服务器数
        ArrayList vmservers = new ArrayList();
        Hashtable threads = new Hashtable();
        
        
        //error \cf1
        //info \cf2
        //warning \cf3
        // \cf0 默认
        // /par 段落
        string rtf_begin = "{\\rtf1\\ansi\\ansicpg936\\deff0\\deflang1033\\deflangfe2052{\\fonttbl{\\f0\\fnil\\fcharset134 \\'cb\\'ce\\'cc\\'e5;}}\r\n{\\colortbl ;\\red255\\green0\\blue0;\\red0\\green176\\blue80;\\red247\\green150\\blue70;}\r\n\\viewkind4\\uc1\\pard\\sl240\\slmult1\\lang2052\\f0\\fs22 ";
        string rtf_end = "}\r\n";
        string logs_buf;
        public VmSearcher()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
            PrintLog(log_level.LOG_INFO, "VmwareSearcher Started ...");
            Settings s = new Settings();
            s.LoadConfig(VMWARE_SEARCHER_CONFIG_FILE);
            config = s.getConfig();
            if (config.isAutoConnect > 0)
            {
                //
                PrintLog(log_level.LOG_INFO, "Enable Auto Connect...");
                //PrintLog(log_level.LOG_INFO, "自动连接服务器...");
                for (int i = 0; i < config.servers.Count; i++)
                {
                    VmServer server = (VmServer)config.servers[i];
                    Thread cont = new Thread(new ParameterizedThreadStart(conThread));
                    PrintLog(log_level.LOG_INFO, "Try to establish connection to " + server.serverIP + "...");
                    cont.Start(new conThreadParam(this,server));
                    threads.Add(server.serverIP, cont);
                }
            }
        }
        void ReloadConfig(Config newconfig)
        {
            foreach (VmServer s in newconfig.servers)
            {
                string newserverIp = s.serverIP;
                bool isConnected = false;
                for (int i = 0; i < vmservers.Count; i++)
                {
                    string existName = ((VmwreIterator)vmservers[i]).GetServerIp();
                    if (existName.Contains(newserverIp) == true)
                    {
                        isConnected = true;
                        break;
                    }
                }
                if (isConnected == false)
                {
                    Thread cont = new Thread(new ParameterizedThreadStart(conThread));
                    PrintLog(log_level.LOG_INFO, "Try to establish connection to " + s.serverIP + "...");
                    cont.Start(new conThreadParam(this, s));
                    threads.Add(s.serverIP, cont);
                }
            }
        }

        private void onSetting_Click(object sender, EventArgs e)
        {
            Settings s = new Settings();
            s.LoadConfig(VMWARE_SEARCHER_CONFIG_FILE);
            s.refreshDate();
            if (s.ShowDialog(this) == DialogResult.OK)
            {
                // Read the contents of testDialog's TextBox. 
                //this.txtResult.Text = testDialog.TextBox1.Text;
                ReloadConfig(s.getConfig());
                config = s.getConfig();
                s.SaveConfig(VMWARE_SEARCHER_CONFIG_FILE);
            }
            else
            {
                //this.txtResult.Text = "Cancelled";
            }
            s.Dispose();

        }
        /// <summary>
        /// 获取GB2312编码
        /// </summary>
        /// <returns></returns>
        static string GetGB2312Code(string Chars)
        {
            string Result = string.Empty;
            byte[] gb2312 = Encoding.GetEncoding("gb2312").GetBytes(Chars);

            foreach (byte b in gb2312)
            {
                Result += "\\'" + string.Format("{0:x2}", b);
            }
            return Result;
        }
        //验证字符是否为汉字
        static bool IsChina(char chr)
        {
            if (Convert.ToInt32(chr) < Convert.ToInt32(Convert.ToChar(128)))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        
        /// <summary>
        /// 打印日志
        /// </summary>
        /// <param name="level"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        //public int  PrintLog(log_level level, string msg,bool refresh_and_scroll_to_end = false)
        public int PrintLog(log_level level, string msg)
        {
            string delimiter = " "; //"\\tab"
            string time_str = DateTime.Now.ToString();

            logs_buf += "\\cf0 " + time_str;
            string s1 = "";
            for (int i = 0; i < msg.Length; i++)
            {
                if (IsChina(msg[i]) == true)
                {
                    s1 += GetGB2312Code(msg.Substring(i,1));
                }
                else
                {
                    s1 += msg.Substring(i, 1);
                }
            }


            switch (level)
            {
                case log_level.LOG_DEBUG:
                    logs_buf += " [Debug]" + delimiter + s1 + "\\par";
                    break;
                case log_level.LOG_ERROR:
                    logs_buf += " [\\cf1 Error\\cf0 ]" + delimiter + "\\cf1 " + s1 + "\\par";
                    break;
                case log_level.LOG_INFO:
                    logs_buf += " [\\cf2 Info\\cf0 ]" + delimiter + "\\cf2 " + s1 + "\\par";
                    break;
                case log_level.LOG_WARNING:
                    logs_buf += " [\\cf3 Warning\\cf0 ]" + delimiter+ "\\cf3 " + s1 + "\\par";
                    break;
            }       

            //logs_richTextBox1.Text += 
            //logs_richTextBox1.Clear();

            try
            {
                logs_richTextBox1.Rtf = rtf_begin + logs_buf + rtf_end;
                logs_richTextBox1.Refresh();
                //if (refresh_and_scroll_to_end == true)
                if (level != log_level.LOG_DEBUG)
                {
                    logs_richTextBox1.SelectionStart = logs_richTextBox1.Text.Length; //Set the current caret position at the end
                    logs_richTextBox1.ScrollToCaret(); //Now scroll it automatically
                }
            }
            catch (Exception e)
            {
                //ignore
            }            
            return 0;
        }
        /// <summary>
        /// 执行按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void on_do_Click(object sender, EventArgs e)
        {
            if (connections_num <= 0)
            {
                PrintLog(log_level.LOG_ERROR, "Server is not connected,Please connect to the server at first!");
            }
            for (int i = 0; i < vmservers.Count; i++)
            {
                VmwreIterator vi = (VmwreIterator)vmservers[i];
                string viname = vi.GetServerIp();
                Thread dothread = new Thread(new ParameterizedThreadStart(doThread));
                //PrintLog(log_level.LOG_INFO, "Exec in " + viname + "...");
                SearchFilter sf = new SearchFilter(this);
                try
                {
                    sf.ParseCmd(expression_comboBox1.Text);
                    dothread.Start(new doThreadParam(this, vi,sf));
                    threads.Add(viname, dothread);
                }
                catch (Exception excep)
                {
                    PrintLog(log_level.LOG_ERROR, excep.ToString());
                }
            }
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void on_connect_Click(object sender, EventArgs e)
        {
            string aaa = logs_richTextBox1.Rtf;
            string bbb = "";
            //logs_richTextBox1.LoadFile("F:\\tmp\\文档.rtf");
        }

        private void button4_Click(object sender, EventArgs e)
        {
            About about = new About();
            about.ShowDialog();
            about.Dispose();
        }


        struct conThreadParam
        {
            public VmSearcher vmsercher;
            public VmServer server;
            public conThreadParam(VmSearcher _vmsercher, VmServer _server)
            {
                vmsercher = _vmsercher;
                server = _server;
            }
        }
        private static void conThread(object obj)
        {
            conThreadParam param = (conThreadParam)obj;
            string connectParamstr = "--url https://";
            connectParamstr += param.server.serverIP + "/sdk";
            connectParamstr += " --portnumber " + param.vmsercher.config.portnumber;
            connectParamstr += " --username " + param.server.serverUserName;
            connectParamstr += " --password " + param.server.serverPassword;
            connectParamstr += " " + param.vmsercher.config.defParam;
            string[] constrs = connectParamstr.Split(new  Char[]{' '});
            VmwreIterator vi = new VmwreIterator();
            try
            {                
                vi.init(constrs);
                param.vmsercher.PrintLog(log_level.LOG_INFO, param.server.serverIP + " is connected!");
                param.vmsercher.connections_num++;
                param.vmsercher.vmservers.Add(vi);
            }
            catch (Exception e)
            {
                if (e.GetType() == typeof(ThreadAbortException))
                {
                    return;
                }
                param.vmsercher.PrintLog(log_level.LOG_ERROR, e.ToString());
                param.vmsercher.PrintLog(log_level.LOG_ERROR, "Failded connection to " + param.server.serverIP + "!");
            }
            finally
            {
                param.vmsercher.threads.Remove(param.server.serverIP);
            }            
        }

        struct doThreadParam
        {
            public VmSearcher vmsercher;
            public VmwreIterator vi;
            public SearchFilter _sf;
            public doThreadParam(VmSearcher _vmsercher, VmwreIterator _vi, SearchFilter sf)
            {
                vmsercher = _vmsercher;
                vi = _vi;
                _sf = sf;
            }
        }
        private static void doThread(object param)
        {
            doThreadParam dp = (doThreadParam)param;
            VmSearcher vms = (VmSearcher)dp.vmsercher;
            VmwreIterator vi = (VmwreIterator)dp.vi;
            vi.doSearch(dp._sf);

        }
        private void OnClose(object sender, FormClosedEventArgs e)
        {
            foreach (DictionaryEntry de in threads)
            {
                ((Thread)de.Value).Abort();
            }
        }

        
    }

    public class Config
    {
        public int isAutoConnect = 0;  //是否自动连接服务器
        public ArrayList servers = new ArrayList();
        public String portnumber;
        public String defParam;
    }
}
